package viper.receive;

import java.lang.System;

//SlidingWindowThread private class
//Function: Manage sliding window algorithm for rcvBuffer
//1. windowIndex is first window in range of sliding window
//2. When first window is filled sufficiently (2/3 packets), send to de-diversification program
//3. If first window timeouts, drop packet 

public class SlidingWinThread implements Runnable {
	long startTime, endTime;
	int startIndex;
	int winIndex;
	
	public void run(){
		winIndex = CallReceiver.WINDOW_INDEX;
		startIndex = winIndex;
		startTime = System.currentTimeMillis();
		endTime = startTime + CallReceiver.TIMEOUT;
		boolean b = false; 
		
		//Implement timeout on first window
		while (endTime >= System.currentTimeMillis()) {
			//Currently implementation for 3,2,3 code only
			
			//Packet A and B are received
			if((CallReceiver.RCV_BUFFER[winIndex][0]!=null)&&(CallReceiver.RCV_BUFFER[winIndex][1]!=null))
				b = true;
			//Packet A and A^B are received
			else if((CallReceiver.RCV_BUFFER[winIndex][0]!=null)&&(CallReceiver.RCV_BUFFER[winIndex][2]!=null))
				b = true;
			//Packer B and A^B are received
			else if((CallReceiver.RCV_BUFFER[winIndex][1]!=null)&&(CallReceiver.RCV_BUFFER[winIndex][2]!=null))
				b = true;
			
			//If window is "full enough", then
			if(b){
				//Send packet to de-diversification program
				dediversify(CallReceiver.WINDOW_INDEX);
				CallReceiver.WINDOW_INDEX++;
				
				//Wrap around window index #s id RCV_BUFFER is full
				if(winIndex == (CallReceiver.RCV_BUFFER_SZ - CallReceiver.WINDOW_INDEX)){
					int i =0;
					for(i=0; i < winIndex; i++){
						CallReceiver.RCV_BUFFER[i] = null;
					}
					CallReceiver.WINDOW_INDEX = 0;
				}
				break;
			}
		}
		
		//If first window timeouts, drop packet
		if(startIndex == CallReceiver.WINDOW_INDEX)
			CallReceiver.WINDOW_INDEX++;
		
		//Wrap around window index #s id RCV_BUFFER is full
		if(winIndex == (CallReceiver.RCV_BUFFER_SZ - CallReceiver.WINDOW_SIZE)){
			int i =0;
			for(i=0; i < winIndex; i++){
				CallReceiver.RCV_BUFFER[i] = null;
			}
			CallReceiver.WINDOW_INDEX = 0;
		}	
	}

	
	//De-diversification of audio packets to send to player audio stream. 
	public void dediversify(int index){
		byte[] buffRecovered = new byte[CallReceiver.MAX_PKT_SZ];
		byte[] buff1 = CallReceiver.RCV_BUFFER[CallReceiver.WINDOW_INDEX][0];
		byte[] buff2 = CallReceiver.RCV_BUFFER[CallReceiver.WINDOW_INDEX][1];
		byte[] buff3 = CallReceiver.RCV_BUFFER[CallReceiver.WINDOW_INDEX][2];
		
		if((buff1 != null)&&(buff2 != null)){
			//if packet type 1 and type 2 are received, update stream RXLS
			CallReceiver.RXLS.update(buff1);
			CallReceiver.RXLS.update(buff2);
		}
		
		if((buff1 != null)&&(buff3 != null)){
			//if packet type 1 and type 3 are received, recover type 2 and then update stream RXLS
			//recover packet type 2
			for(int i=0; i<buffRecovered.length; i++){
				buffRecovered[i] = (byte)(buff1[i]^buff3[i]);
			}
			
			CallReceiver.RXLS.update(buff1);
			CallReceiver.RXLS.update(buffRecovered);
		}
		
		if((buff2 != null)&&(buff3 != null)){
			//if packet type 2 and type 3 are received, recover type 1 and then update stream RXLS
			//recover packet type 1
			for(int i=0; i<buffRecovered.length; i++){
				buffRecovered[i] = (byte)(buff2[i]^buff3[i]);
			}
			
			CallReceiver.RXLS.update(buffRecovered);
			CallReceiver.RXLS.update(buff2);
		}
						
	}
	
}




